#pragma once
#include "utils.hpp"
#include <mutex>

namespace Cloud
{
#define CONFIG_FILE_PATH "./config.conf"
    class Config
    {
    public:
        static Config *getInstance()
        {
            if (_instance == nullptr)
            {
                _mutex.lock();
                if (_instance == nullptr)
                    _instance = new Config();
                _mutex.unlock();
            }
            return _instance;
        }

        const size_t getHotTime() const { return _hotTime; }
        const size_t getServerPort() const { return _serverPort; }
        const std::string& getServerIp() const { return _serverIp; }
        const std::string& getDownloadPrefix() const { return _downloadPrefix; }
        const std::string& getPackfileSuffix() const { return _packfileSuffix; }
        const std::string& getPackDir() const { return _packDir; }
        const std::string& getBackDir() const { return _backDir; }
        const std::string& getBackupFile() const { return _backupFile; }
        void update() { readConfigFile(); }
        void show() const
        {
            std::cout << "hotTime:        " << _hotTime << std::endl;
            std::cout << "serverPort:     " << _serverPort << std::endl;
            std::cout << "serverIp:       " << _serverIp << std::endl;
            std::cout << "downloadPrefix: " << _downloadPrefix << std::endl;
            std::cout << "packfileSuffix: " << _packfileSuffix << std::endl;
            std::cout << "packDir:        " << _packDir << std::endl;
            std::cout << "backDir:        " << _backDir << std::endl;
            std::cout << "backupFile:     " << _backupFile << std::endl;
        }

    private:
        Config() 
        {
            std::cout << "readConfigFile..." << std::endl;
            readConfigFile(); 
            std::cout << "check..." << std::endl;
            check(); // 读了配置信息才能检查,不然你连要检查什么都不知道
        }
        Config(const Config &) = delete;
        Config operator=(const Config &) = delete;
        void readConfigFile()
        {
            std::string config;
            if (FileUtils(CONFIG_FILE_PATH).getContent(&config) == false)
            {
                std::cout << "Read config file error\n";
                return;
            }
            Json::Value root;
            JsonUtils::deSerialize(config, &root);
            _hotTime = root["hot_time"].asInt64();
            _serverPort = root["server_port"].asInt64();
            _serverIp = root["server_ip"].asString();
            _downloadPrefix = root["download_prefix"].asString();
            _packfileSuffix = root["packfile_suffix"].asString();
            _packDir = root["pack_dir"].asString();
            _backDir = root["back_dir"].asString();
            _backupFile = root["backup_file"].asString();
            show();
            std::cout << "read Config file done!\n";
        }
        void check()
        {
            std::cout << "checkDir..." << std::endl;
            checkDir();
            std::cout << "checkBackupFile..." << std::endl;
            checkBackupFile();
        }
        
        void checkDir()
        {
            FileUtils d1 = FileUtils(_backDir);
            if (!d1.exists())
                d1.createDirectory();
            FileUtils d2 = FileUtils(_packDir);
            if (!d2.exists())
                d2.createDirectory();
        }
        void checkBackupFile()
        {
            if(!FileUtils(_backupFile).exists())
                FileUtils(_backupFile).setContent("");
        }

    private:
        size_t _hotTime;
        size_t _serverPort;
        std::string _serverIp;
        std::string _downloadPrefix;
        std::string _packfileSuffix;
        std::string _packDir;
        std::string _backDir;
        std::string _backupFile;

    private:
        static Config *_instance;
        static std::mutex _mutex;
    };
    std::mutex Config::_mutex;
    Config *Config::_instance = nullptr;
}